#include "vo.h"

#include <stdio.h>

#include "mpi_vo.h"
#include "mpi_vo_dev.h"

#define COLOR_RGB_RED 0xFF0000
#define COLOR_RGB_GREEN 0x00FF00
#define COLOR_RGB_BLUE 0x0000FF
#define COLOR_RGB_BLACK 0x000000
#define COLOR_RGB_YELLOW 0xFFFF00
#define COLOR_RGB_CYN 0x00ffff
#define COLOR_RGB_WHITE 0xffffff

HI_S32 VO_Init(VO_DEV VoDev, VO_LAYER VoLayer, VO_CHN VoChn)
{
    HI_S32 s32Ret = 0;

    VO_PUB_ATTR_S stVoPubAttr =
        {
            .enIntfType = VO_INTF_MIPI,
            .enIntfSync = VO_OUTPUT_USER,
            .stSyncInfo =
                {
                    .bSynm = 0,
                    .bIop = 1,
                    .u8Intfb = 0,

                    .u16Vact = 800,
                    .u16Vbb = 24,
                    .u16Vfb = 20,

                    .u16Hact = 480,
                    .u16Hbb = 60,
                    .u16Hfb = 50,
                    .u16Hmid = 1,

                    .u16Bvact = 1,
                    .u16Bvbb = 1,
                    .u16Bvfb = 1,

                    .u16Hpw = 10,
                    .u16Vpw = 4,

                    .bIdv = 0,
                    .bIhs = 0,
                    .bIvs = 0,
                },
            .u32BgColor = COLOR_RGB_BLUE,
        };

    VO_USER_INTFSYNC_INFO_S stUserInfo =
        {
            .stUserIntfSyncAttr =
                {
                    .enClkSource = VO_CLK_SOURCE_PLL,
                    .stUserSyncPll =
                        {
                            .u32Fbdiv = 244,
                            .u32Frac = 0x1A36,
                            .u32Refdiv = 4,
                            .u32Postdiv1 = 7,
                            .u32Postdiv2 = 7,
                        },
                },
            .u32PreDiv = 1,
            .u32DevDiv = 1,
            .bClkReverse = HI_TRUE,
        };

    VO_VIDEO_LAYER_ATTR_S stLayerAttr =
        {
            .stDispRect =
                {
                    .s32X = 0,
                    .s32Y = 0,
                    .u32Width = 480,
                    .u32Height = 800,
                },
            .stImageSize =
                {
                    .u32Width = 480,
                    .u32Height = 800,
                },
            .u32DispFrmRt = 60,
            .enPixFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            .bDoubleFrame = HI_FALSE,
            .bClusterMode = HI_FALSE,
            .enDstDynamicRange = DYNAMIC_RANGE_SDR8,
        };

    s32Ret = HI_MPI_VO_SetPubAttr(VoDev, &stVoPubAttr);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetPubAttr: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_SetDevFrameRate(VoDev, 60);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetDevFrameRate: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_SetUserIntfSyncInfo(VoDev, &stUserInfo);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetUserIntfSyncInfo: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_Enable(VoDev);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_Enable: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_SetDisplayBufLen(VoLayer, 3);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetDisplayBufLen: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_SetVideoLayerAttr(VoLayer, &stLayerAttr);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetVideoLayerAttr: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_EnableVideoLayer(VoLayer);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_EnableVideoLayer: %x\n", s32Ret);
        return HI_FAILURE;
    }

    if (VO_INTF_MIPI == stVoPubAttr.enIntfType)
    {
        VO_CSC_S stVideoCSC = {0};
        s32Ret = HI_MPI_VO_GetVideoLayerCSC(VoDev, &stVideoCSC);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] HI_MPI_VO_GetVideoLayerCSC: %x\n", s32Ret);
            return HI_FAILURE;
        }

        stVideoCSC.enCscMatrix = VO_CSC_MATRIX_BT709_TO_RGB_PC;
        s32Ret = HI_MPI_VO_SetVideoLayerCSC(VoDev, &stVideoCSC);
        if (HI_SUCCESS != s32Ret)
        {
            printf("[FAIL] HI_MPI_VO_SetVideoLayerCSC: %x\n", s32Ret);
            return HI_FAILURE;
        }
    }

    VO_CHN_ATTR_S stChnAttr =
        {
            .u32Priority = 0,
            .stRect =
                {
                    .s32X = 0,
                    .s32Y = 0,
                    .u32Width = 480,
                    .u32Height = 800,
                },
            .bDeflicker = HI_FALSE,
        };

    s32Ret = HI_MPI_VO_SetChnAttr(VoLayer, VoChn, &stChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetChnAttr: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_SetChnRotation(VoLayer, VoChn, ROTATION_90);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_SetChnRotation: %x\n", s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VO_EnableChn(VoLayer, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_EnableChn: %x\n", s32Ret);
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

HI_VOID VO_DeInit(VO_DEV VoDev, VO_LAYER VoLayer, VO_CHN VoChn)
{
    HI_S32 s32Ret = 0;

    s32Ret = HI_MPI_VO_DisableChn(VoLayer, VoChn);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_DisableChn: %x\n", s32Ret);
    }

    s32Ret = HI_MPI_VO_DisableVideoLayer(VoLayer);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_DisableVideoLayer: %x\n", s32Ret);
    }

    s32Ret = HI_MPI_VO_Disable(VoDev);
    if (HI_SUCCESS != s32Ret)
    {
        printf("[FAIL] HI_MPI_VO_Disable: %x\n", s32Ret);
    }
}
